package com.katze.boot.system.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.katze.boot.common.domain.ActiveUser;
import com.katze.boot.plugins.redis.service.CacheService;
import com.katze.boot.system.dao.UserMapper;
import com.katze.boot.system.domain.DeptUsers;
import com.katze.boot.system.domain.User;
import com.katze.boot.system.domain.UserRole;
import com.katze.boot.system.service.UserRoleService;
import com.katze.boot.system.service.UserService;
import com.katze.boot.system.service.UserSetupService;
import com.katze.common.Pagination;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.Collection;
import java.util.Date;
import java.util.List;

@Service("userService")
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class)
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    @Autowired
    private UserRoleService userRoleService;
    @Autowired
    private UserSetupService userSetupService;
    @Autowired
    private PasswordEncoder encoder;
    @Autowired
    private CacheService cacheService;

    @Override
    public boolean exists(String username, String... password) {
        LambdaQueryWrapper<User> wrapper = Wrappers.lambdaQuery(User.class)
                .eq(User::getUsername, username);
        if (password.length == 1) {
            wrapper.eq(User::getPassword, encoder.encode(password[0]));
        }
        return this.exists(wrapper);
    }

    @Override
    public User getUserDetails(String username) {
        return this.baseMapper.getUserDetails(username);
    }

    @Override
    public List<ActiveUser> findUserByUsernames(Collection<String> username) {
        return this.baseMapper.findActiveUserByUsernames(username);
    }

    @Override
    public IPage<User> findUsers(Pagination request, User user) {
        return this.baseMapper.findUsers(request.toPage(), user);
    }

    @Override
    @Transactional
    public void updateLoginTime(User user) {
        LambdaUpdateWrapper<User> wrapper = Wrappers.lambdaUpdate(User.class)
                .set(User::getLastLoginTime, user.getLastLoginTime())
                .set(User::getLastLoginIp, user.getLastLoginIp())
                .set(User::getLastLoginLocation, user.getLastLoginLocation())
                .eq(User::getUsername, user.getUsername());
        super.update(wrapper);
    }

    @Override
    @Transactional
    public void createUser(User user) {
        // 创建用户
        user.setCreateTime(new Date());
        user.setPassword(encoder.encode(User.DEFAULT_PASSWORD));
        user.setStatus(User.STATUS_NORMAL);
        this.save(user);
        // 保存用户角色
        this.userRoleService.save(user);
        // 创建用户默认的个性化配置
        this.userSetupService.initDefaultUserSetup(user.getUsername());
    }

    @Override
    @Transactional
    public void updateUser(User user) {
        // 更新用户
        LambdaUpdateWrapper<User> wrapper = Wrappers.lambdaUpdate(User.class)
                .set(User::getFirstname, user.getFirstname())
                .set(User::getMobile, user.getMobile())
                .set(User::getEmail, user.getEmail())
                .set(User::getSex, user.getSex())
                .set(User::getStatus, user.getStatus())
                .set(User::getAddress, user.getAddress())
                .set(User::getBirthDate, user.getBirthDate())
                .set(User::getDeptId, user.getDeptId())
                .set(User::getDescription, user.getDescription())
                .set(User::getModifyTime, new Date())
                .eq(User::getUserId, user.getUserId());
        super.update(wrapper);

        // 修改用户角色，并清除用户权限缓存
        String username = this.userRoleService.resetUserRoles(user).apply(baseMapper::getUserDetails);
        this.cacheService.clearUserCache(username);
    }

    @Override
    @Transactional
    public void deleteUsers(String... usernames) {
        for (String username : usernames) {
            // 先删除相应的缓存
            this.cacheService.logout(username);
            // 删除用户, 用户个性化配置, 用户角色
            this.baseMapper.deleteUserByUsername(username);
        }
    }

    @Override
    @Transactional
    public void updateProfile(User user) {
        LambdaUpdateWrapper<User> wrapper = Wrappers.lambdaUpdate(User.class)
                .set(StringUtils.isNotBlank(user.getFirstname()), User::getFirstname, user.getFirstname())
                .set(StringUtils.isNotBlank(user.getSex()), User::getSex, user.getSex())
                .set(StringUtils.isNotBlank(user.getMobile()), User::getMobile, user.getMobile())
                .set(StringUtils.isNotBlank(user.getEmail()), User::getEmail, user.getEmail())
                .set(StringUtils.isNotBlank(user.getAvatar()), User::getAvatar, user.getAvatar())
                .set(StringUtils.isNotBlank(user.getStatus()), User::getStatus, user.getStatus());
        if (user.getBirthDate() != null) {
            wrapper.set(User::getBirthDate, user.getBirthDate().trim());
        }
        if (user.getDescription() != null) {
            wrapper.set(User::getDescription, user.getDescription().trim());
        }
        if (user.getAddress() != null) {
            wrapper.set(User::getAddress, user.getAddress().trim());
        }
        wrapper.eq(User::getUserId, user.getUserId());
        super.update(wrapper);
    }

    @Override
    @Transactional
    public void updateAvatar(String username, String avatar) {
        LambdaUpdateWrapper<User> wrapper = Wrappers.lambdaUpdate(User.class)
                .set(User::getAvatar, avatar)
                .eq(User::getUsername, username);
        super.update(wrapper);
    }

    @Override
    @Transactional
    public void updatePassword(String username, String password) {
        LambdaUpdateWrapper<User> wrapper = Wrappers.lambdaUpdate(User.class)
                .set(User::getPassword, encoder.encode(password))
                .eq(User::getUsername, username);
        super.update(wrapper);
    }

    @Override
    @Transactional
    public void regist(String username, String password) {
        User user = new User();
        user.setPassword(encoder.encode(password));
        user.setUsername(username);
        user.setCreateTime(new Date());
        user.setStatus(User.STATUS_LOCK);
        user.setSex(User.SEX_UNKNOW);
        user.setDescription("注册用户");
        super.save(user);

        // 2:注册用户角色 ID
        this.userRoleService.save(new UserRole(user.getUserId(), 2L));

        // 创建用户默认的个性化配置
        this.userSetupService.initDefaultUserSetup(username);
    }

    @Override
    @Transactional
    public void resetPassword(String[] usernames) {
        for (String username : usernames) {
            User user = new User();
            user.setPassword(encoder.encode(User.DEFAULT_PASSWORD));
            this.baseMapper.update(user, new LambdaQueryWrapper<User>().eq(User::getUsername, username));
        }
    }

    @Override
    public String findSubordinates(Long deptId) {
        return this.baseMapper.findSubordinates(deptId);
    }

    @Override
    public List<DeptUsers> findSubordinatesMap() {
        return this.baseMapper.findSubordinatesMap();
    }
}